package data

import (
	"bytes"
	"fmt"
	"gitchina/kly_service/util"
	"github.com/astaxie/beego/orm"
	_ "github.com/go-sql-driver/mysql"
	"strconv"
)

type LinePubDto struct {
	Id              int     `orm:"pk;auto;column(id)"`
	MemberId        int     `orm:"column(member_id)"`
	SrcProvince     int     `orm:"column(src_province)"`
	SrcCity         int     `orm:"column(src_city)"`
	SrcCounty       int     `orm:"column(src_county)"`
	DestProvince    int     `orm:"column(dest_province)"`
	DestCity        int     `orm:"column(dest_city)"`
	DestCounty      int     `orm:"column(dest_county)"`
	HeavyCargoPrice float32 `orm:"column(heavy_cargo_price)"`
	LightCargoPrice float32 `orm:"column(light_cargo_price)"`
	BasePrice       float32 `orm:"column(base_price)"`
	TermOfValidity  int     `orm:"column(term_of_validity)"`
	State           int     `orm:"column(state)"`
}

type LinePubListDto struct {
	OwnerName       string  `orm:"column(name)"`
	OwnerPhone      string  `orm:"column(phone)"`
	OwnerId         int     `orm:"column(member_id)"`
	OwnerPhoto      string  `orm:"column(photo)"`
	CorpName        string  `orm:"column(corp_name)"`
	LinePubId       int     `orm:"column(pub_id)"`
	SrcProvince     int     `orm:"column(src_province)"`
	SrcCity         int     `orm:"column(src_city)"`
	SrcCounty       int     `orm:"column(src_county)"`
	DestProvince    int     `orm:"column(dest_province)"`
	DestCity        int     `orm:"column(dest_city)"`
	DestCounty      int     `orm:"column(dest_county)"`
	HeavyCargoPrice float32 `orm:"column(heavy_cargo_price)"`
	LightCargoPrice float32 `orm:"column(light_cargo_price)"`
	BasePrice       float32 `orm:"column(base_price)"`
	State           int     `orm:"column(state)"`
	TermOfValidity  int     `orm:"column(term_of_validity)"`
}

type QueryLinePubListParam struct {
	StartArea       int
	EndArea         int
	CorpName        string
	HeavyCargoPrice string
	LightCargoPrice string
	PageNo          int
	PageSize        int
}

type LinePubDetail struct {
	OwnerName       string  `orm:"column(name)"`
	OwnerPhone      string  `orm:"column(phone)"`
	OwnerId         int     `orm:"column(member_id)"`
	OwnerPhoto      string  `orm:"column(photo)"`
	CorpName        string  `orm:"column(corp_name)"`
	LinePubId       int     `orm:"column(pub_id)"`
	SrcProvince     int     `orm:"column(src_province)"`
	SrcCity         int     `orm:"column(src_city)"`
	SrcCounty       int     `orm:"column(src_county)"`
	DestProvince    int     `orm:"column(dest_province)"`
	DestCity        int     `orm:"column(dest_city)"`
	DestCounty      int     `orm:"column(dest_county)"`
	HeavyCargoPrice float32 `orm:"column(heavy_cargo_price)"`
	LightCargoPrice float32 `orm:"column(light_cargo_price)"`
	BasePrice       float32 `orm:"column(base_price)"`
	TermOfValidity  int     `orm:"column(term_of_validity)"`
	State           int     `orm:"column(state)"`
	Intro           string  `orm:"intro"`
}

type RecommendListDto struct {
	Id           int    `orm:"column(id)"`
	EmpPhotoUrl  string `orm:"column(emp_photo_url)"`
	CorpName     string `orm:"column(corp_name)"`
	SrcProvince  int    `orm:"column(src_province)"`
	SrcCity      int    `orm:"column(src_city)"`
	SrcCounty    int    `orm:"column(src_county)"`
	DestProvince int    `orm:"column(dest_province)"`
	DestCity     int    `orm:"column(dest_city)"`
	DestCounty   int    `orm:"column(dest_county)"`
}

func init() {
	orm.RegisterModel(new(LinePubDto))
}

func (l *LinePubDto) TableName() string {
	return "l_line_pub"
}

func (l LogisticsRepo) AddLinePub(dto *LinePubDto) (id int64, err error) {
	var num int64
	var list orm.ParamsList
	o := orm.NewOrm()
	num, err = o.Raw(SQL_Logis_Last_Line_Pub, dto.MemberId, dto.SrcProvince, dto.SrcCity, dto.SrcCounty, dto.DestProvince, dto.DestCity, dto.DestCounty).ValuesFlat(&list)
	if err == nil {
		if num == 0 {
			id, err = o.Insert(dto)
		} else {
			id = 0
		}
	}

	return
}

func (l LogisticsRepo) UpdateLine(dto *LinePubDto) (err error) {
	o := orm.NewOrm()
	_, err = o.Raw(SQL_Logis_Update_Line, dto.SrcProvince, dto.SrcCity, dto.SrcCounty, dto.DestProvince, dto.DestCity, dto.DestCounty, dto.TermOfValidity, dto.HeavyCargoPrice, dto.LightCargoPrice, dto.BasePrice, dto.Id, dto.MemberId).Exec()
	return
}

func (l LogisticsRepo) CancelLine(mbrId, lineId int) (err error) {
	o := orm.NewOrm()
	_, err = o.Raw(SQL_Logis_Cancel_Line, lineId, mbrId).Exec()
	return
}

func (l LogisticsRepo) RecoverLine(mbrId, lineId int) (err error) {
	o := orm.NewOrm()
	_, err = o.Raw(SQL_Logis_Recover_Line, lineId, mbrId).Exec()
	return
}

func (l LogisticsRepo) GetLinePubs(memberId, pageNo, pageSize int, queryState string) ([]LinePubDto, int, error) {
	var num int64
	var rowCount int
	var err error
	var flat orm.ParamsList
	var pubs []LinePubDto
	o := orm.NewOrm()

	var stateWhere string
	if queryState == "1" {
		stateWhere = " AND state = 0"
	} else if queryState == "2" {
		stateWhere = " AND state = 1"
	}

	if num, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Line_Pub, stateWhere, (pageNo-1)*pageSize, pageSize), memberId).QueryRows(&pubs); num >= 1 {
		if num, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Line_Pub_Count, stateWhere), memberId).ValuesFlat(&flat); num >= 1 {
			rowCount, err = strconv.Atoi(flat[0].(string))
			util.GetLogger().Debug("[data-QueryLinePubList] - debug:rowcount::%s", flat[0])
		}
	}

	return pubs, rowCount, err
}

func (l LogisticsRepo) QueryLinePubList(param QueryLinePubListParam) ([]LinePubListDto, int, error) {
	var list []LinePubListDto
	var flat orm.ParamsList
	var err error
	var num int64
	var rowCount int
	o := orm.NewOrm()
	format, args := l.getQueryLinePubListCond(param, false)
	countFormat, countArgs := l.getQueryLinePubListCond(param, true)
	if num, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Line_Pub_List, format), args).QueryRows(&list); num >= 1 {
		if num, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Line_Pub_List_Count, countFormat), countArgs).ValuesFlat(&flat); num >= 1 {
			rowCount, err = strconv.Atoi(flat[0].(string))
			util.GetLogger().Debug("[data-QueryLinePubList] - debug:rowcount::%s", flat[0])
		}
	}
	return list, rowCount, err
}

func (l LogisticsRepo) GetLinePubDetail(pubId int) (LinePubDetail, error) {
	var detail LinePubDetail
	o := orm.NewOrm()
	err := o.Raw(SQL_Logis_Get_Line_Pub_Detail, pubId).QueryRow(&detail)
	return detail, err
}

func (l LogisticsRepo) GetRecommendLineList(startArea, pageSize int) (list []RecommendListDto, err error) {
	o := orm.NewOrm()
	_, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Recommend_Line, pageSize)).QueryRows(&list)

	//omit filter
	//_, err = o.Raw(fmt.Sprintf(SQL_Logis_Get_Recommend_Line, pageSize), startArea).QueryRows(&list)
	return
}

func (r LogisticsRepo) getQueryLinePubListCond(param QueryLinePubListParam, ignoreLimit bool) (string, []interface{}) {
	var buffer bytes.Buffer
	var args = make([]interface{}, 0)
	if param.StartArea != 0 {
		if param.StartArea%10000 == 0 {
			buffer.WriteString(" AND src_province = ?")
		} else if param.StartArea%100 == 0 {
			buffer.WriteString(" AND src_city = ?")
		} else {
			buffer.WriteString(" AND src_county = ?")
		}
		args = append(args, param.StartArea)
	}
	if param.EndArea != 0 {
		if param.EndArea%10000 == 0 {
			buffer.WriteString(" AND dest_province = ?")
		} else if param.EndArea%100 == 0 {
			buffer.WriteString(" AND dest_city = ?")
		} else {
			buffer.WriteString(" AND dest_county = ?")
		}
		args = append(args, param.EndArea)
	}

	if param.HeavyCargoPrice != "" {
		buffer.WriteString(" AND p.heavy_cargo_price = ?")
		args = append(args, param.HeavyCargoPrice)
	}

	if param.LightCargoPrice != "" {
		buffer.WriteString(" AND p.light_cargo_price = ?")
		args = append(args, param.LightCargoPrice)
	}

	if param.CorpName != "" {
		buffer.WriteString(" AND l.name LIKE '%" + param.CorpName + "%'")
	}

	if !ignoreLimit {
		buffer.WriteString(fmt.Sprintf(" ORDER BY p.id DESC LIMIT %d, %d", (param.PageNo-1)*param.PageSize, param.PageSize))
	}

	return buffer.String(), args
}
